package com.springboot.crawler.service;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomNode;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlTable;
import com.springboot.crawler.constant.RegionConstant;
import com.springboot.crawler.dao.SysAreaInfDao;
import com.springboot.crawler.dto.SysAreaInfDto;
import com.springboot.crawler.po.SysAreaInfPo;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by dongfangchao on 2017/6/1/0001.
 */
@Service
public class RegionCrawlServiceImpl {

    @Autowired
    private SysAreaInfDao sysAreaInfDao;

    @Transactional
    public void provinceCrawl() throws Exception{
        WebClient webClient = new WebClient(BrowserVersion.CHROME);
        webClient.getOptions().setCssEnabled(false);
        webClient.getOptions().setJavaScriptEnabled(false);
        HtmlPage page = webClient.getPage(RegionConstant.REGION_BASE_URL + "/index.html");
        HtmlTable table = page.querySelector(RegionConstant.PROVINCE_TABLE_CLASS);
        if (table != null){
            DomNodeList<DomNode> aList = table.querySelectorAll("a");
            aList.forEach(item -> {
                try {
                    String regionName = item.getTextContent();
                    String subUrl = RegionConstant.REGION_BASE_URL + item.getAttributes().getNamedItem("href").getTextContent();

                    SysAreaInfPo po = new SysAreaInfPo();
                    po.setName(regionName);
                    po.setFullName(regionName);
                    po.setSubUrl(subUrl);
                    po.setTreePath(",");

                    SysAreaInfPo provinceDbPo = sysAreaInfDao.save(po);

                    SysAreaInfDto provinceDto = new SysAreaInfDto();
                    PropertyUtils.copyProperties(provinceDto, provinceDbPo);
                    cityCrawl(provinceDto);
                    Thread.sleep(5000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        webClient.close();
    }

    @Transactional
    public void cityCrawl(SysAreaInfDto provinceDto) throws Exception{
        List<SysAreaInfDto> cityList = regionCrawl(provinceDto.getSubUrl(), RegionConstant.CITY_TABLE_CLASS, RegionConstant.CITY_TR_CLASS);
        if (!CollectionUtils.isEmpty(cityList)){
            cityList.forEach(item -> {
                try {
                    SysAreaInfPo po = new SysAreaInfPo();
                    PropertyUtils.copyProperties(po, item);
                    po.setParent(provinceDto.getId());
                    po.setFullName(provinceDto.getFullName() + item.getName());
                    po.setTreePath(provinceDto.getTreePath() + provinceDto.getId() + ",");

                    SysAreaInfPo cityDbPo = sysAreaInfDao.save(po);

                    SysAreaInfDto cityDto = new SysAreaInfDto();
                    PropertyUtils.copyProperties(cityDto, cityDbPo);
                    countyCrawl(cityDto);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }

    @Transactional
    public void countyCrawl(SysAreaInfDto cityDto) throws Exception{
        List<SysAreaInfDto> countyList = regionCrawl(cityDto.getSubUrl(), RegionConstant.COUNTY_TABLE_CLASS, RegionConstant.COUNTY_TR_CLASS);
        if (!CollectionUtils.isEmpty(countyList)){
            countyList.forEach(item -> {
                try {
                    SysAreaInfPo po = new SysAreaInfPo();
                    PropertyUtils.copyProperties(po, item);
                    po.setParent(cityDto.getId());
                    po.setFullName(cityDto.getFullName() + item.getName());
                    po.setTreePath(cityDto.getTreePath() + cityDto.getId() + ",");

                    SysAreaInfPo countyDbPo = sysAreaInfDao.save(po);
                    SysAreaInfDto countyDto = new SysAreaInfDto();
                    PropertyUtils.copyProperties(countyDto, countyDbPo);

                    townCrawl(countyDto);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }

    @Transactional
    public void townCrawl(SysAreaInfDto countyDto) throws Exception{
        List<SysAreaInfDto> townList = regionCrawl(countyDto.getSubUrl(), RegionConstant.TOWN_TABLE_CLASS, RegionConstant.TOWN_TR_CLASS);
        if (!CollectionUtils.isEmpty(townList)){
            townList.forEach(item -> {
                try {
                    SysAreaInfPo po = new SysAreaInfPo();
                    PropertyUtils.copyProperties(po, item);
                    po.setParent(countyDto.getId());
                    po.setFullName(countyDto.getFullName() + item.getName());
                    po.setTreePath(countyDto.getTreePath() + countyDto.getId() + ",");

                    sysAreaInfDao.save(po);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }

    public List<SysAreaInfDto> regionCrawl(String crawlUrl, String tableClass, String trClass) throws Exception{
        if (StringUtils.isEmpty(crawlUrl)){
            return null;
        }

        List<SysAreaInfDto> sysAreaInfList = new ArrayList<>();

        for (int j =0 ; j < 3; j++){
            try {
                System.out.println("crawlUrl = " + crawlUrl);
                WebClient webClient = new WebClient(BrowserVersion.CHROME);
                webClient.getOptions().setCssEnabled(false);
                webClient.getOptions().setJavaScriptEnabled(false);
                HtmlPage page = webClient.getPage(crawlUrl);
                HtmlTable table = page.querySelector(tableClass);
                if (table != null){
                    DomNodeList<DomNode> trList = table.querySelectorAll(trClass);
                    for (int i = 0; i < trList.size(); i++){
                        DomNode trNode = trList.get(i);

                        String gbcode = "";
                        String regionName = "";
                        String subUrl = "";

                        DomNodeList<DomNode> aList = trNode.querySelectorAll("a");
                        if (CollectionUtils.isEmpty(aList)){
                            DomNodeList<DomNode> tdList = trNode.querySelectorAll("td");
                            if (!CollectionUtils.isEmpty(tdList)){
                                gbcode = tdList.get(0).getTextContent();
                                regionName = tdList.get(1).getTextContent();
                            }
                        }else {
                            gbcode = aList.get(0).getTextContent();
                            regionName = aList.get(1).getTextContent();
                            subUrl = crawlUrl.substring(0, crawlUrl.lastIndexOf("/") + 1) + aList.get(0).getAttributes().getNamedItem("href").getTextContent();
                        }

                        SysAreaInfDto dto = new SysAreaInfDto();
                        dto.setSubUrl(subUrl);
                        dto.setName(regionName);
                        dto.setGbCode(gbcode);

                        sysAreaInfList.add(dto);
                    }
                }
                webClient.close();
                break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return sysAreaInfList;
    }

}
